package btp.Calendars;

public class JulianCalendar {

        public static final int JANUARY = 1;
        public static final int FEBRUARY = 2;
        public static final int MARCH = 3;
        public static final int APRIL = 4;
        public static final int MAY = 5;
        public static final int JUNE = 6;
        public static final int JULY = 7;
        public static final int AUGUST = 8;
        public static final int SEPTEMBER = 9;
        public static final int OCTOBER = 10;
        public static final int NOVEMBER = 11;
        public static final int DECEMBER = 12;
        
/*      
 * The epoch of the Gregorian calendar, i.e., R.D.1 corresponds to January 3, 1 (Julian). 
 * Therefore the Julian epoch coincides with December 30, 0 (Gregorian).
*/
        public static final int EPOCH = (int) GregorianCalendar.getRDFromGregorian(0, GregorianCalendar.DECEMBER, 30);

        
        protected int year;
        protected int month;
        protected int day;
        protected boolean leap;
        
        public JulianCalendar(int year,int month,int day)
        {
                setYear(year);
                setMonth(month);
                setDay(day);
        }
        
        protected void setLeap(){
                leap = isYearLeap(year);
        }
        
        public boolean isLeap(){
                return leap;
        }
        
        public int getYear() {
                return year;
        }
        public void setYear(int year) {
                this.year = year;
                setLeap();
        }
        public int getMonth() {
                return month;
        }
        public void setMonth(int month) {
                this.month = month;
        }
        public int getDay() {
                return day;
        }
        public void setDay(int day) {
                this.day = day;
        }
        
        public long getRDFromJulian(){
                return getRDFromJulian(year, month, day);
        }

        public static boolean isYearLeap(int year){
                return (year>0)?(year%4==0):(year%4==-1);
        }

        
        public static long getRDFromJulian(int year, int month, int day){
                int y = year<0?year+1:year;
                return (long) (EPOCH - 1 + 365*(y-1) + Math.floor((y-1)/4.0)+ Math.floor((367*month-362)/12.0) + (month<=2?0:(isYearLeap(year)?-1:-2)) + day);
        }
        
        public static JulianCalendar getJulianDayFromRD(long rd){
                long approx = (long) Math.floor((4*(rd-EPOCH)+1464)/1461.0);
                int year = (int) (approx<=0?approx-1:approx);
                int priorDays = (int) (rd - getRDFromJulian(year, JANUARY, 1));
                int correction = (rd<getRDFromJulian(year, MARCH, 1))?0:(isYearLeap(year)?1:2);
                int month = (int) Math.floor((12*(priorDays+correction)+373)/367.0);
                int day = (int) (rd - getRDFromJulian(year, month, 1)+1);
                return new JulianCalendar(year, month, day);
        }
        
}
